package com.bee.bootstrap.plugs.shiro;
import com.bee.bootstrap.constant.RedisCacheKey;
import com.bee.bootstrap.plugs.redis.RedisCacheManager;
import com.bee.bootstrap.roleResource.service.IRoleResourceService;
import com.bee.bootstrap.user.entity.User;
import com.bee.bootstrap.user.service.IUserService;
import com.bee.bootstrap.userRole.service.IUserRoleService;
import com.bee.common.core.constant.Constant;
import com.bee.common.tools.context.SpringContextUtil;
import com.bee.common.tools.jwt.JwtUtils;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Service;
import java.util.Map;

/**
 * 配合shrio使用的jwtRealm
 */
@Service("jwtRealm")
public class JwtRealm extends AuthorizingRealm {


    private JwtUtils jwtUtils;
    private IUserService userServiceImpl;
    private IUserRoleService userRoleServiceImpl;
    private IRoleResourceService roleResourceServiceImpl;
    private RedisCacheManager redisCacheManager;


    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        userRoleServiceImpl= (IUserRoleService) SpringContextUtil.getBean("userRoleService");
        roleResourceServiceImpl=(IRoleResourceService) SpringContextUtil.getBean("roleResourceService");
        String Authorization = new String(Base64.decodeBase64(principals.toString().getBytes()));
        User user = userServiceImpl.findUserByToken(Authorization);
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.addRoles(userRoleServiceImpl.findRolesCodes(user.getId()));
        simpleAuthorizationInfo.addStringPermissions(roleResourceServiceImpl.findResourcePermission(user.getId()));
        return simpleAuthorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String principal = (String) authenticationToken.getPrincipal();
        String credentials=(String) authenticationToken.getCredentials();
        if(StringUtils.isBlank(principal)){
            throw new AuthenticationException("token无效");
        }
        jwtUtils=(JwtUtils) SpringContextUtil.getBean("jwtUtils");
        userServiceImpl= (IUserService) SpringContextUtil.getBean("userService");
        redisCacheManager= (RedisCacheManager) SpringContextUtil.getBean("redisCacheManager");
        roleResourceServiceImpl=(IRoleResourceService) SpringContextUtil.getBean("roleResourceService");
        String authorization = new String(Base64.decodeBase64(principal.toString().getBytes()));
        try {
            Map<String,Object> data=jwtUtils.checkToken(authorization, Constant.JWT_ISSUER,Constant.JWT_ISSUER);
            Object phone=data.getOrDefault("phone","");
            if (phone == null) {
                throw new AuthenticationException("token无效");
            }
            User user=userServiceImpl.findUserByPhone(phone.toString());
            if (user == null) {
                throw new AuthenticationException("用户不存在");
            }
            //缓存权限
            if(redisCacheManager.getCache(RedisCacheKey.RESOURCE_KEY).get(principal)==null)
                redisCacheManager.getCache(RedisCacheKey.RESOURCE_KEY).put(principal,roleResourceServiceImpl.findResources(user.getId()));
            return new SimpleAuthenticationInfo(principal, credentials, "jwtRealm");
        }catch (Exception e){
            throw new AuthenticationException("token无效");
        }
    }

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }

    public void clearCache(String token){
        String authorization = new String(Base64.encodeBase64(token.getBytes()));
        redisCacheManager= (RedisCacheManager) SpringContextUtil.getBean("redisCacheManager");
        if( redisCacheManager.getCache(RedisCacheKey.RESOURCE_KEY).get(authorization)!=null){
            redisCacheManager.getCache(RedisCacheKey.RESOURCE_KEY).remove(authorization);
        }
        Cache<Object, Object> cache = redisCacheManager.getCache(JwtRealm.class.getName()+".authorizationCache");
        cache.remove(authorization);
    }
}
